package com.yy.service.front.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yy.entity.front.User;
import com.yy.mapper.front.UserMapper;
import com.yy.service.front.UserService;
import com.yy.utils.MD5Utils;
import com.yy.utils.R;
import com.yy.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * create by KongFuning on 2022/8/4
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /*
    * 发送验证码
    * */
    @Override
    public R sendCode(String phone) {
        log.info("phone:{}",phone);
        if (RegexUtils.isPhoneInvalid(phone)) {
            return R.error("非法手机号格式！");
        }
        // 1、生成验证码
        String code = RandomUtil.randomNumbers(4);
        // 2、保存验证码到Redis
        stringRedisTemplate.opsForValue().set("login:code:" + phone,code,2L, TimeUnit.MINUTES);
        // 3、发送验证码
        log.debug("发送短信验证码成功，验证码：{} 2分钟后过期",code);
        return R.success("短信验证码发送成功");
    }

    @Override
    @Transactional
    public R login(HttpServletRequest request, Map loginMap) {
        // 1、校验手机号
        String phone = (String) loginMap.get("phone");
        if (RegexUtils.isPhoneInvalid(phone)) {
            return R.error("手机号格式错误！");
        }
        // 2、从redis中获取验证码
        String cacheCode = stringRedisTemplate.opsForValue().get("login:code:" + phone);
        // 3、获取用户输入的验证码
        String code = (String) loginMap.get("code");
        if(cacheCode == null || !cacheCode.equals(code)){
            return R.error("验证码错误！");
        }
        // 4、根据手机号查询用户
        User user = query().eq("phone", phone).one();
        if(user == null){
            // 5、用户不存在，则直接创建用户并保存到数据库
            user = createUserWithPhone(phone);
        }
        // 6、保存用户信息到Redis中
        // 6.1、随机生成token，作为登录令牌
        String token = UUID.randomUUID().toString(true);
        // 6.2 将User对象转化为Hash存储
        Map<String, Object> userMap = BeanUtil.beanToMap(user,new HashMap<>(),
                CopyOptions.create().setIgnoreNullValue(true)
                .setFieldValueEditor((fieldName,fieldValue) -> fieldValue != null ? fieldValue.toString() : ""));
        // 6.3、存储
//        stringRedisTemplate.opsForHash().putAll("login:token:" + token,userMap);
        request.getSession().setAttribute("user",user.getId());
        // 6.4 设置token有效期
//        stringRedisTemplate.expire("login:token:" + token, 30L,TimeUnit.MINUTES);

        return R.success(token);
    }

    public User createUserWithPhone(String phone){
        User user = new User();
        // 设置id
        user.setId(UUID.randomUUID().toString(true));
        // 设置用户名
        user.setName("user_" + MD5Utils.code(phone));
        // 设置手机号
        user.setPhone(phone);
        save(user);
        log.debug("新用户保存成功：{}",user.getPhone());
        return user;
    }
}
